#include "ResourceManager.h"
#include <QDir>
#include <QFile>
#include <time.h>
#include "ResourceLoader.h"
#include "ClassMetaManager.h"
#include "CommonExceptions.h"



_NS_OOP_BEGIN



ResourceManager::ResourceManager () :
_dir ("res/")
{
	srand (time (NULL));
}



ResourceManager::~ResourceManager ()
{
}



void
ResourceManager::setResourceDirectory (const QString& r_dir)
throw (InvalidArgumentException)
{
	if (!QDir (r_dir).exists ())
		OOPTHROW (InvalidArgumentException (
				QString ("The directory '%1' is not found").arg (r_dir)));
	_dir = r_dir;
}



void
ResourceManager::releaseAll ()
{
	_objects.clear ();
	_loadSquence.clear ();
}



void
ResourceManager::_checkAndCorrectName (P_Object p_obj) const
{
	if (p_obj->name ().isEmpty ()) {
		QString name;
		do {
			name = QString ("rnd_%1").arg (rand () % 1000000, 6, 10, QChar ('0'));
		} while (_doesNameExist (name));
		p_obj->name (name);
	} else if (p_obj->name () == "NULL") {
		OOPTHROW (InvalidArgumentException (QString ("Object name cannot be null")));
 	} else if (_doesNameExist (p_obj->name ())) {
 		QString tmpName;
 		do {
 			tmpName = QString ("%1_%2").arg (p_obj->name ())
 					.arg (rand () % 1000000, 6, 10, QChar ('0'));
 		} while (_doesNameExist (tmpName));
 		p_obj->name (tmpName);
 	}
}



bool
ResourceManager::_doesNameExist (const QString& r_name) const
{
	return QDir (_dir).exists (r_name);
}



void
ResourceManager::_recordLoadedObject (P_Object p_obj)
{
	_loadSquence.enqueue (p_obj->name ());
	auto& r_entry = _objects[p_obj->name ()];
	if (r_entry.first == NULL) {
		r_entry.first = p_obj;
		r_entry.second = 1;
	} else
		++r_entry.second;
}



void
ResourceManager::_clean ()
{
	auto nObjects = _objects.size ();
	auto nSquenceLength = _loadSquence.size ();
	int nVisited = 0;
	do {
		auto name = _loadSquence.front ();
		_loadSquence.dequeue ();
		auto& r_entry = _objects[name];
		if (r_entry.first->getRefNum () == 1) {
			--r_entry.second;
			if (r_entry.second == 0)
				_objects.remove (name);
		} else
			_loadSquence.enqueue (name);
		++nVisited;
	} while (_objects.size () > nObjects / 2 && nVisited < nSquenceLength);
}



_NS_OOP_END

